home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / App / Sources / UVUAssist.cp < prev   
Encoding:
Text File  |  1996-04-03  |  39.4 KB  |  1,353 lines  |  [TEXT/MPS ]

  1. // UVUAssist.cp
  2. // Copyright © 1991-96 by Apple Computer, Inc., all rights reserved.
  3.  
  4. //    Contains:    VU assistance methods
  5. //    Version: 2.0d1 - MacApp 3.1 compatible version
  6.  
  7. /*
  8. Historical Note:  References to the "Mole" are equivalent to references to "Agent VU".
  9. "Agent VU" was previously called the "Mole".
  10.  
  11. The mole sees MacApp windows as plain windows that are empty.  MacApp
  12. doesn't put its controls in the control list, so V.U. won't even see standard
  13. Control Manager controls.  The assistance proc updates the mole buffer before
  14. it is sent back to the V.U. host, telling it that there are items in the windows, 
  15. and telling it about each item.  We tell it that the windows are dialogs, 
  16. because V.U. looks for a wider range of user interface items in dialogs.
  17.  
  18. V.U. has its own hierarchy of user interface items, based largely on the types of 
  19. interface items defined in Inside Mac which V.U. can obtain information about
  20. in non-MacApp applications.  MacApp's user interface element hierarchy is the view hierarchy.  
  21. Since the two hierarchies are not the same, VUAssist must perform a mapping between the
  22. two hierarchies.  Many of these mappings are straight-forward, but a few require some
  23. explanation.  The V.U. interface item hierarchy is as follows.  
  24.  
  25.                 |___ staticText
  26.                 |                       
  27.                 |___ editText                       
  28.                 |                                          
  29.                 |___ picture
  30. contentItem-----|
  31.                 |___ icon                       
  32.                 |                                          
  33.                 |___ userItem
  34.                 |
  35.                 |___ control-----|___ button
  36.                                   |                       
  37.                                   |___ checkBox
  38.                                  |
  39.                                  |___ radioButton
  40.                                   |                       
  41.                                   |___ scrollBar
  42.                                  |                       
  43.                                   |___ popup
  44.                                  
  45. All V.U. interface items are considered contentItems.  Some of these contentItems are 
  46. typically found only in Dialog Manager dialogs in non-MacApp applications.  These would 
  47. be staticText, editText, picture, icon, and userItem.  Controls are Control Manager controls
  48. which may appear in any window.
  49.  
  50. The list of TView descendants which are mapped to V.U. interface items and the V.U. item
  51. to which they are mapped by V.U. by way of VUAssist is shown below.
  52.  
  53. TStaticText ---------> staticText
  54. TEditText     ---------> editText
  55. TPicture     ---------> picture
  56. TIcon         ---------> icon
  57. TButton     ---------> button
  58. TCheckbox     ---------> checkBox
  59. TRadio         ---------> radioButton
  60. TScrollBar     ---------> scrollBar
  61. TPopup         ---------> popup
  62. TTextEdit     ---------> editText
  63. (cells of TGridView -> contentItem)  - an optional feature
  64.  
  65. The last item, "cells of TGridView", deserves some explanation. TGridViews are a 
  66. problem because unlike all the other items mentioned above, where there is exactly one 
  67. MacApp object for each user interface item, there are many user interface items for a 
  68. single TGridView object.  V.U. does not yet directly support gridView types of objects.  
  69. So there is special case code for TGridViews.  Each cell in a grid is passed back as a 
  70. "CUSTOM_ITEM".  To V.U., a CUSTOM_ITEM is a user interface item which does not fall into
  71. any category more specific than contentItem.  So from a V.U. script writer's perspective,
  72. cells in TGridView objects are V.U. contentItems.
  73.  
  74. Note that the mapping of TGridView cells to contentItems is a feature which can be disabled.
  75. TVUAssist's IVUAssist method takes a Boolean argument gridItemSupport.  By passing 'false'
  76. to this method, the cells of TGridViews are invisible to V.U..  You may want to do this if 
  77. your application has large gridviews or many gridviews.  In this case treating each cell as
  78. an interface item may bog down V.U. in such a way that performance is not acceptable. 
  79.  
  80. You'll also note in the code that we include TPopup descriptions in response to V.U.'s requests 
  81. for information about controls.  This is because V.U. can normally only support popups which 
  82. are implemented through the use of the popup CDEF found in System 7.0 or in the Mac Communications 
  83. Toolbox.  So V.U. expects them to be controls. */
  84.  
  85. /*========================================== TVUAssist ================================*/
  86.  
  87. #if qNeedsVU
  88.  
  89. /* ----------------- VUAssist includes -------------------- */
  90.  
  91. #ifndef __UVUASSIST__
  92. #include "UVUAssist.h"
  93. #endif
  94.  
  95. // MacApp
  96.  
  97. #ifndef __UAPPLICATION__
  98. #include "UApplication.h"
  99. #endif
  100.  
  101. #ifndef __UDIALOG__
  102. #include "UDialog.h"
  103. #endif
  104.  
  105. #ifndef __UGRIDVIEW__
  106. #include "UGridView.h"
  107. #endif
  108.  
  109. #ifndef __UPOPUP__
  110. #include "UPopup.h"
  111. #endif
  112.  
  113. #ifndef __UWINDOW__
  114. #include "UWindow.h"
  115. #endif
  116.  
  117. // Toolbox
  118.  
  119. #ifndef __TOOLUTILS__
  120. #include <ToolUtils.h>
  121. #endif
  122.  
  123. #ifndef __DEVICES__
  124. #include <Devices.h>
  125. #endif
  126.     
  127. #ifndef __FILES__
  128. #include <Files.h>
  129. #endif
  130.     
  131. /* ----------------- VUAssist typedefs -------------------- */
  132.  
  133. typedef TCtlMgr *TCtlMgrPtr;
  134. typedef TControl *TControlPtr;
  135. typedef TStaticText *TStaticTextPtr;
  136. typedef TEditText *TEditTextPtr;
  137. typedef TGridView *TGridViewPtr;
  138. typedef TTEView *TTEViewPtr;
  139. typedef TGridView *TGridViewPtr;
  140. typedef TPopup *TPopupPtr;
  141. typedef TTextGridView *TTextGridViewPtr;
  142. typedef TGridItem *TGridItemPtr;
  143.  
  144. //========================================================================================
  145. // GLOBAL
  146. //========================================================================================
  147.  
  148. static long MAMoleHook(long select, Ptr input, Ptr output, short *outputSize, long result);
  149.  
  150.  
  151. /* ----------------- VUAssist global -------------------- */
  152.  
  153. TVUAssist *gVUAssist;
  154. MoleHookUPP    gMoleHookUPP = NewMoleHookProc(MAMoleHook);
  155.  
  156. /* ----------------- VUAssist macros -------------------- */
  157.  
  158. // pascal string length macro
  159. ////#define VUPstrLength(str) (short)(*(char *)str) 
  160.  
  161. inline short VUPLstrlen(void* s)        { return (short)(*(unsigned char *)s); }
  162.  
  163. //========================================================================================
  164. // CLASS TVUAssist
  165. //========================================================================================
  166. #undef Inherited
  167. #define Inherited TEventHandler
  168.  
  169. #pragma segment AInit
  170. MA_DEFINE_CLASS_M1(TVUAssist, Inherited);
  171.  
  172. //----------------------------------------------------------------------------------------
  173. // TVUAssist destructor
  174. //----------------------------------------------------------------------------------------
  175. #pragma segment MADestructorRes
  176.  
  177. TVUAssist::~TVUAssist()
  178. {
  179. }
  180.  
  181. #pragma segment AVUAssist
  182. /* MAMoleHook accepts the call from the mole with a C interface, and then calls
  183. TVUAssist::MoleAssist. */
  184.  
  185. long MAMoleHook(long select, Ptr input, Ptr output, short *outputSize, long result)
  186. {
  187. #if !qPowerPC
  188.     long oldA5 = SetCurrentA5();
  189. #endif
  190.     MoleError aMoleError = gVUAssist->MoleAssist(select, input, output, outputSize, result);
  191. #if !qPowerPC
  192.     SetA5(oldA5);
  193. #endif
  194.     return aMoleError;
  195. }
  196.  
  197. /* IVUAssist initializes fMoleRefNum.  fMoleRefNum contains the reference number of the 
  198. mole driver, or 0 if no mole driver has been found yet. Also initializes VUAssist as an EventHandler
  199. and initializes fGridItemSupport according to input argument gridItemSupport.*/
  200.  
  201. void TVUAssist::IVUAssist(Boolean gridItemSupport)
  202. {
  203.     Inherited::IEventHandler(NULL);
  204.     fGridItemSupport = gridItemSupport;
  205.     fMoleRefNum = 0;
  206.     this->OpenMoleDriver();
  207. }
  208.  
  209.  
  210. /* Try to open the mole driver if there is one. */
  211.  
  212. void TVUAssist::OpenMoleDriver()
  213. {
  214.     ParamBlockRec aPBRec;
  215.     short Err;
  216.  
  217.     aPBRec.ioParam.ioCompletion = NULL;
  218.     aPBRec.ioParam.ioNamePtr = (StringPtr)StripAddress("\p.Mole");
  219.     aPBRec.ioParam.ioPermssn = fsCurPerm;
  220.     Err = PBOpenSync(&aPBRec);
  221.     if (Err == noErr) {
  222.         fMoleRefNum = aPBRec.ioParam.ioRefNum;
  223.         this->ResumeMole();
  224.     }
  225. }
  226.  
  227. /* Call this routine when the application is suspended by Multifinder, to let
  228. the mole know we are no longer the frontmost app. */
  229.  
  230. void TVUAssist::SuspendMole()
  231. {
  232.     this->SetDebuggerHook(NULL);
  233. }
  234.  
  235.  
  236. /* Call this routine when MultiFinder puts us back into the foreground. */
  237.  
  238. void TVUAssist::ResumeMole() 
  239. {
  240.     this->SetDebuggerHook(gMoleHookUPP);
  241. }
  242.  
  243.  
  244. /* This is the routine called by MAMoleHook.  It dispatches out to the routines
  245. which actually assist the mole. */
  246.  
  247. MoleError TVUAssist::MoleAssist (long select, Ptr input, Ptr output, short *outputSize, long intResult)
  248. {
  249.     MoleError ret = MoleError(intResult);
  250.     MoleError result = MoleError(intResult);
  251.     
  252.     switch (select) {
  253.  
  254.     case SMenuInfo:
  255.         ret = this->DoMenuInfo (input, output, outputSize, result);
  256.         break;
  257.  
  258.     case SMenuItems:
  259.         ret = this->DoMenuItems (input, output, outputSize, result);
  260.         break;
  261.  
  262.     case SWindInfo:
  263.         ret = this->DoSendWindowInfo (input, output, outputSize, result);
  264.         break;
  265.  
  266.     case SFindCtl:
  267.         ret = this->DoFindControl (input, output, outputSize, result);
  268.         break;
  269.  
  270.     case SCtlInfo:
  271.         ret = this->DoSendControlInfo (input, output, outputSize, result);
  272.         break;
  273.  
  274.     case SDItemInfo:
  275.         ret = this->DoSendDlogItemInfo (input, output, outputSize, result);
  276.         break;
  277.  
  278.     case SetMItemKey:
  279.     case SFrontWind:
  280.     case SFindWind:
  281.     case SFindDItem:
  282.     default:
  283.         break;
  284.     }
  285.     return ret;
  286. }
  287.  
  288.  
  289. #define SET_ASSIST 100
  290.  
  291. /* Tell the mole the address of our assistance procedure.*/
  292.  
  293. void TVUAssist::SetDebuggerHook (MoleHookUPP theNewHook)
  294. {
  295.     if (fMoleRefNum)
  296.     {
  297.         ParamBlockRec aPBRec;
  298.         
  299.         aPBRec.cntrlParam.ioCompletion = NULL;
  300.         aPBRec.cntrlParam.ioVRefNum = 0;
  301.         aPBRec.ioParam.ioRefNum = fMoleRefNum;
  302.         aPBRec.cntrlParam.csCode = SET_ASSIST;
  303.         *((long *)&(aPBRec.cntrlParam.csParam[0])) = (long)theNewHook;
  304.         ::PBControlAsync(&aPBRec);
  305. #if qDebug
  306.         if (aPBRec.cntrlParam.ioResult) 
  307.         {
  308.             ProgramBreak("Error sending Agent VU control call");
  309.         }
  310. #endif
  311.     }
  312. }
  313.  
  314.  
  315.  
  316. /* ------------------------------------------------------------------------------------ */
  317. /* the routines for handling individual mole requests.  Each routine handles
  318.   exactly one mole request. */
  319.  
  320. /*
  321. |    Handle a request for specific menu items.  The Mole can get info on menus in the
  322. |    menu bar, but we have to supply info on popup menus. If the Input data specifies
  323. |    a non-zero menu ID, use the ID to determine the popup menu.  Otherwise, if the 
  324. |    the menu rank input parameter is 0 (unspecified) use the menu handle input parameter
  325. |    directly to identify the popup menu. We do not deal with menus specified by non-zero
  326. |    rank parameter (where the menu ID parameter is 0.
  327. */
  328. MoleError TVUAssist::DoMenuItems (Ptr input, Ptr output, short *outputSize, MoleError result) 
  329. {
  330.     SendMenuItemsParamsPtr    menuReqPtr;
  331.     MoleDataBlockPtr        menuDescPtr;
  332.     TPopup                    *popup;
  333.     MenuRef                    theMenuRef;
  334.     
  335.     if (result != mNoErr) /* only do the work if agent needs help */
  336.     {
  337.         menuReqPtr = SendMenuItemsParamsPtr(input);
  338.         menuDescPtr = MoleDataBlockPtr(output);
  339.         theMenuRef = NULL;
  340.         
  341.         if (menuReqPtr->menu_ID != 0)
  342.         {
  343.             popup = this->MenuIDToPopup(menuReqPtr->menu_ID);
  344.             if (popup != NULL)
  345.             {
  346.                 theMenuRef = popup->GetMenuRef();
  347.             }
  348.         }
  349.         else if (menuReqPtr->menu_rank == 0)
  350.         {
  351.             if (menuReqPtr->menu_hdl != NULL)
  352.             {
  353.                 theMenuRef = menuReqPtr->menu_hdl;
  354.             }
  355.         }
  356.         if (theMenuRef != NULL)
  357.         {
  358.             result = this->FillPopupItemDesc(theMenuRef, menuReqPtr->start_item, 
  359.                                              menuReqPtr->stop_item, menuDescPtr, outputSize);
  360.         }
  361.     }
  362.     return result;
  363. }
  364.  
  365.  
  366. /*
  367. |    Handle a request for menu info.  The Mole can get info on menus in the
  368. |    menu bar, but we have to supply info on popup menus. If the Input data specifies
  369. |    a non-zero menu ID, use the ID to determine the popup menu.  Otherwise, if the 
  370. |    the menu rank input parameter is 0 (unspecified) use the menu handle input parameter
  371. |    directly to identify the popup menu. We do not deal with menus specified by non-zero
  372. |    rank parameter (where the menu ID parameter is 0.
  373. */
  374. MoleError TVUAssist::DoMenuInfo (Ptr input, Ptr output, short *outputSize, MoleError result)
  375. {
  376.     SendMenuInfoParamsPtr    menuReqPtr;
  377.     MoleMenuInfoPtr         menuDescPtr;
  378.     TPopup                     *popup;
  379.     MenuRef                    theMenuRef;
  380.  
  381.     if (result != mNoErr)  /* only do the work if agent needs help */
  382.     {
  383.         menuReqPtr = SendMenuInfoParamsPtr(input);
  384.         menuDescPtr = MoleMenuInfoPtr(output);
  385.         theMenuRef = NULL;
  386.         
  387.         if (menuReqPtr->menu_ID != 0)
  388.         {
  389.             popup = this->MenuIDToPopup(menuReqPtr->menu_ID);
  390.             if (popup != NULL)
  391.             {
  392.                 theMenuRef = popup->GetMenuRef();
  393.             }        
  394.         }
  395.         else if (menuReqPtr->menu_rank == 0)
  396.         {
  397.             if (menuReqPtr->menu_hdl != NULL)
  398.             {
  399.                 theMenuRef = menuReqPtr->menu_hdl;
  400.             }
  401.         }
  402.         if (theMenuRef != NULL)
  403.         {
  404.             this->FillPopupDesc(theMenuRef, RANK_OF_THE_INVISIBLE, menuDescPtr, outputSize);
  405.             result = mNoErr;
  406.         }
  407.     }
  408.     return result;
  409. }
  410.  
  411.  
  412. /* Revise the values of the controlCount and numItems fields of the MoleWDescPtr, given
  413. knowledge of MacApp views. Also update validFlags and windowKind fields. WindowKind is set 
  414. to dialogKind so that V.U. will look for things that it can normally only see in dialogs 
  415. (such as icons and pictures) */
  416.  
  417. MoleError TVUAssist::DoSendWindowInfo (Ptr input, Ptr output, short *, MoleError result)
  418. {
  419.     DWindReqPtr windReqPtr;
  420.     MoleWDescPtr windDescPtr;
  421.     TWindow *window;
  422.  
  423.     windReqPtr = DWindReqPtr(input);
  424.     windDescPtr = MoleWDescPtr(output);
  425.     window = this->RankToWindow (*windReqPtr);
  426.     if (window) { 
  427.         windDescPtr->validFlags |= (VCTLCNT_MASK | VITEMCNT_MASK);
  428.         windDescPtr->windowKind = dialogKind;
  429.         windDescPtr->controlCount = this->ViewCount (window, FALSE);
  430.         windDescPtr->numItems = this->ViewCount (window, TRUE);
  431.         /* outputSize is filled in by the mole */
  432.         return mNoErr;
  433.     }
  434.  
  435.     return result;
  436. }
  437.  
  438.  
  439. /* The mole sends us a point location in global coordinates.  We need to figure out
  440. which window and which control that point is in (if any), and send back info about
  441. that control. V.U. utilizes this routine for theControl Manager controls (TCtlMgr) only.*/
  442.  
  443. MoleError TVUAssist::DoFindControl (Ptr input, Ptr output, short *outputSize, MoleError result)
  444. {
  445.     SendFindControlParamPtr ctrlReqPtr;
  446.     MoleCDescPtr ctrlDescPtr;
  447.     SendFindControlParam targetPoint;
  448.     short part;
  449.     WindowRef wind;
  450.     WindowRef windowPtr;
  451.     GrafPtr savePort;
  452.     TCtlMgr *theControl;
  453.     short rank;
  454.     ControlRef saveCtlList;
  455.     ControlRef WhichCtl;
  456.     TWindow *window;
  457.     VPoint VPt;
  458.  
  459.     ctrlReqPtr = SendFindControlParamPtr(input);
  460.     targetPoint = *ctrlReqPtr;
  461.     ctrlDescPtr = MoleCDescPtr(output);
  462.  
  463.     part = ::FindWindow(targetPoint, &windowPtr);
  464.     wind = windowPtr;
  465.  
  466.     /* The mole also tests for part=inSysWindow, but we'll let the mole handle those cases */
  467.     if (wind && (part == inContent)) {
  468.         window = gApplication->WMgrToWindow(WindowRef(wind));
  469.         if (window) {
  470.             theControl = this->PointToControl (window, targetPoint, &rank);
  471.             if (theControl) {
  472.                 part = -1;
  473.                 /* Get the control part code.  Controls are not kept in the controllist,
  474.                 so we temporarily put them in there.  Also, they are in their subviews
  475.                 local coordinate system, so we must convert targetpoint. */
  476.                 ::GetPort (&savePort);
  477.                 ::SetPort (WindowRef(wind));
  478.                 if (window->Focus()) {
  479.                     saveCtlList = ((WindowPeek) wind)->controlList;
  480.                     ((WindowPeek) wind)->controlList = theControl->fCMgrControl;
  481.                     this->GlobalToWindow (window, targetPoint, &VPt);
  482.                     this->WindowToView (theControl, &VPt, &targetPoint);
  483.                     part = FindControl (targetPoint, WindowRef(wind), &WhichCtl);
  484.                     ((WindowPeek) wind)->controlList = saveCtlList;
  485.                 }
  486.                 ::SetPort (savePort);
  487.  
  488.                 if (this->FillCtrlDesc (ctrlDescPtr, part, this->WindowToRank(wind), rank, theControl, outputSize)) {
  489.                     return mNoErr;
  490.                 }
  491.             }
  492.         }
  493.     }
  494.  
  495.     return result;
  496. }
  497.  
  498.  
  499. /* Read the input parameter to see which control V.U. wants info on, then
  500. fill in the SendCtlInfoParamsPtr record.  The mole can't gather any info about
  501. MacApp controls without our help, so we fill in the whole record, except for part, 
  502. which doesn't apply.*/
  503.  
  504. MoleError TVUAssist::DoSendControlInfo (Ptr input, Ptr output, short *outputSize, MoleError result)
  505. {
  506.     SendCtlInfoParamsPtr ctrlReqPtr;
  507.     MoleCDescPtr ctrlDescPtr;
  508.     TWindow *window;
  509.     TControl *theControl;
  510.     TGridItem *gridItem;
  511.  
  512.     gridItem = NULL;
  513.     ctrlReqPtr = SendCtlInfoParamsPtr(input);
  514.     ctrlDescPtr = MoleCDescPtr(output);
  515.  
  516.     window = this->RankToWindow (ctrlReqPtr->window_rank);
  517.     if (window) {
  518.         theControl = TControlPtr(this->RankToItem(window, ctrlReqPtr->control_rank, FALSE, gridItem));
  519.         if (theControl) {
  520.             if (this->FillCtrlDesc(ctrlDescPtr, -1, ctrlReqPtr->window_rank, ctrlReqPtr->control_rank,
  521.                                    theControl, outputSize)) 
  522.             {
  523.                 return mNoErr;
  524.             }
  525.         }
  526.     }
  527.  
  528.     return result;
  529. }
  530.  
  531.  
  532. /* Read the input to see which dialog item in which window V.U. wants data on, and
  533. fill in the dialogiteminfo record. */
  534. MoleError TVUAssist::DoSendDlogItemInfo (Ptr input, Ptr output, short *outputSize, MoleError result)
  535. {
  536.     SendDItemInfoPtr dlogReqPtr;
  537.     MoleDItemInfoPtr dlogDescPtr;
  538.     TWindow *window;
  539.     TView *view;
  540.     TGridItem *gridItem;
  541.  
  542.     gridItem = NULL;
  543.     dlogReqPtr = SendDItemInfoPtr(input);
  544.     dlogDescPtr = MoleDItemInfoPtr(output);
  545.  
  546.     window = this->RankToWindow (dlogReqPtr->window_rank);
  547.     if (window) {
  548.         view = this->RankToItem (window, dlogReqPtr->item_num, TRUE, gridItem);
  549.         if (view) {
  550.             this->FillDlogItemDesc(dlogDescPtr, window, dlogReqPtr->window_rank, dlogReqPtr->item_num,
  551.                                    view, outputSize, gridItem);
  552.             return mNoErr;
  553.         }
  554.     }
  555.  
  556.     return result;
  557. }
  558.      
  559.  
  560. #pragma segment AVUAssist2
  561.  
  562. /* ------------------------------------------------------------------------------------ */
  563. /* routines for filling in mole data structures */
  564.  
  565. /* Given a TPopup object, fill in the mole's menu descriptor record. */
  566.  
  567. void TVUAssist::FillPopupDesc (MenuRef theMenuHdl, short menuRank, MoleMenuInfoPtr menuDescPtr, short *outputSize)
  568. {
  569.     menuDescPtr->num_items = ::CountMItems(theMenuHdl);
  570.     menuDescPtr->rank = menuRank;
  571.     menuDescPtr->left_edge = 0;
  572.     menuDescPtr->menuID = (**theMenuHdl).menuID;
  573.     menuDescPtr->menuWidth = (**theMenuHdl).menuWidth;
  574.     menuDescPtr->menuHeight = (**theMenuHdl).menuHeight;
  575.     menuDescPtr->enableFlags = (**theMenuHdl).enableFlags;
  576.     MABlockMove((**theMenuHdl).menuData, menuDescPtr->menuTitle.text, VUPLstrlen((**theMenuHdl).menuData)+1);
  577.  
  578.     /* this ugly thing computes the length (bytes used) of MoleMenuInfo */
  579.     *outputSize = sizeof(MoleMenuInfo) - (255 - VUPLstrlen((**theMenuHdl).menuData));
  580. }
  581.  
  582.  
  583. /* this function depends upon Ptr being a pointer to a single byte */
  584.  
  585. static Ptr SeekMenuItem (short ItemNum, MenuRef MenuHdl)
  586. {
  587.     Ptr seekPtr = Ptr(&((**MenuHdl).menuData) + VUPLstrlen((**MenuHdl).menuData) + 1);
  588.     short seekNum = 1;
  589.  
  590.     while ((seekNum < ItemNum) && *seekPtr) {
  591.         seekPtr +=  *seekPtr + ADDITIONAL_MENU_ITEM_DATA;
  592.         seekNum++;
  593.     }
  594.  
  595.     return seekPtr;
  596. }
  597.  
  598.  
  599. /* Given a TPopup object and a menu handle, fill in the mole's menuitem descriptor record. */
  600. MoleError TVUAssist::FillPopupItemDesc (MenuRef theMenuHdl, short start, short stop,
  601.                                         MoleDataBlockPtr menuItemDescPtr, short *outputSize)
  602. {
  603.     Ptr         startPtr;
  604.     Ptr         stopPtr;
  605.     MoleError     ret = mNoErr;
  606.  
  607.     if ((start > ::CountMItems(theMenuHdl)) || (start < 1)) 
  608.     {
  609.         return mBadMenuItemIndex;
  610.     }
  611.  
  612.     if (stop > ::CountMItems(theMenuHdl)) 
  613.     {
  614.         stop = ::CountMItems(theMenuHdl);
  615.         ret = mBadLastMenuItemIndex;
  616.     }
  617.  
  618.     startPtr = SeekMenuItem(start, theMenuHdl);
  619.     stopPtr = SeekMenuItem(stop+1, theMenuHdl);
  620.     if (! (startPtr && stopPtr)) 
  621.     {
  622.         return mBadMenuItemIndex;
  623.     }
  624.  
  625.     menuItemDescPtr->blockLength = stop - start + 1;
  626.     MABlockMove(startPtr, &menuItemDescPtr->dataBlock[0], stopPtr - startPtr);
  627.  
  628.     /* this ugly thing computes the length (bytes used) of MoleDataBlock */
  629.     *outputSize = sizeof(short) + (stopPtr - startPtr);
  630.  
  631.     return ret;
  632. }
  633.  
  634.  
  635. /* Fill in a mole control descriptor record.  Valid descendants of TControl are descendants of
  636. TCtlMgr and TPopup. Will return false if TControl is not a descendant of TCtlMgr or TPopup.*/
  637.  
  638. Boolean TVUAssist::FillCtrlDesc (MoleCDescPtr ctrlDescPtr, short thePart,
  639.                                         short windowRank, short ControlRank,
  640.                                         TControl *theControl, short *outputSize)
  641. {
  642.     ControlRef        ControlHdl;
  643.     VRect             aVRect;
  644.     CRect            aCRect;        
  645.     MenuRef            theMenuHdl;
  646.     unsigned char    *theExtraDataPtr;
  647.     Boolean            itsOdd;
  648.     short            outputSizeAdjustor;
  649.     short            titleLength;
  650.  
  651.     if (MA_MEMBER(theControl, TPopup)) {
  652.  
  653.         theMenuHdl = TPopupPtr(theControl)->GetMenuRef();
  654.         
  655.         ctrlDescPtr->validFlags = VALL_C_MASK;
  656.         if (thePart == -1)    /* indicate that part code is not valid */
  657.         {
  658.             ctrlDescPtr->validFlags = ctrlDescPtr->validFlags & ~VCPART_MASK;
  659.         }
  660.  
  661.         ctrlDescPtr->owner_rank = windowRank;
  662.         theControl->GetExtent (aVRect);
  663.         VRectToRect(aVRect, aCRect);
  664.         SetRect(&ctrlDescPtr->ctlRect, aCRect.left, aCRect.top, aCRect.right, aCRect.bottom);
  665.         this->ViewRectToWindowRect (&ctrlDescPtr->ctlRect, theControl);
  666.  
  667.         ctrlDescPtr->ctlValue = TPopupPtr(theControl)->GetCurrentItem();
  668.         ctrlDescPtr->ctlMin = 1;
  669.         ctrlDescPtr->ctlMax = ::CountMItems(theMenuHdl);
  670.         ctrlDescPtr->ctlHilite = 0;
  671.         if (thePart == -1) 
  672.         {
  673.             ctrlDescPtr->part = 0;
  674.         } 
  675.         else 
  676.         {
  677.             ctrlDescPtr->part = thePart;
  678.         }
  679.         ctrlDescPtr->ctlRank = ControlRank;
  680.         ctrlDescPtr->ctlDefID = POPUP_CDEF * 16;
  681.         ctrlDescPtr->ctlData.popupMenuID = TPopupPtr(theControl)->GetMenuID();
  682.         titleLength = VUPLstrlen((**theMenuHdl).menuData);
  683.         MABlockMove((**theMenuHdl).menuData, ctrlDescPtr->ctlTitle.text, titleLength+1);
  684.  
  685.         /* 
  686.         |    For 7.1, we need to add the menu handle at the first even byte boundary beyond
  687.         |    end of the text_name field.  This determines the location for the
  688.         |    menu handle. 
  689.         */
  690.         theExtraDataPtr = ctrlDescPtr->ctlTitle.text + titleLength + 2;
  691.         if (odd(theExtraDataPtr))
  692.         {
  693.             itsOdd = TRUE;
  694.             theExtraDataPtr = theExtraDataPtr - 1;
  695.         }
  696.         else
  697.         {
  698.             itsOdd = FALSE;
  699.         }
  700.         
  701.         /* Tack the menu handle on the end of the CtrlDescPtr */
  702.         MABlockMove(&theMenuHdl, theExtraDataPtr, sizeof(MenuRef));
  703.  
  704.         /* compute the length (bytes used) of CtrlDescPtr */
  705.         if (itsOdd)
  706.         {
  707.             outputSizeAdjustor = 1;
  708.         }
  709.         else
  710.         {
  711.             outputSizeAdjustor = 2;
  712.         }
  713.         
  714.         /* this ugly thing computes the length (bytes used) of ctrlDescPtr */
  715.         *outputSize = sizeof(MoleControlDescriptor) - (255-titleLength) + outputSizeAdjustor;
  716.         return TRUE;
  717.     } 
  718.     else 
  719.     {
  720.         if (MA_MEMBER(theControl, TCtlMgr)) {
  721.             
  722.             ControlHdl = TCtlMgrPtr(theControl)->fCMgrControl;
  723.             ctrlDescPtr->validFlags = VALL_C_MASK;
  724.             if (thePart == -1)    /* indicate that part code is not valid */
  725.             {
  726.                 ctrlDescPtr->validFlags = ctrlDescPtr->validFlags & ~VCPART_MASK;
  727.             }
  728.             ctrlDescPtr->owner_rank = windowRank;
  729.             ctrlDescPtr->ctlRect = (**ControlHdl).contrlRect;
  730.             this->ViewRectToWindowRect (&ctrlDescPtr->ctlRect, theControl);
  731.             ctrlDescPtr->ctlValue = (**ControlHdl).contrlValue;
  732.             ctrlDescPtr->ctlMin = (**ControlHdl).contrlMin;
  733.             ctrlDescPtr->ctlMax = (**ControlHdl).contrlMax;
  734.             ctrlDescPtr->ctlHilite = (**ControlHdl).contrlHilite;
  735.             if (thePart == -1) {
  736.                 ctrlDescPtr->part = 0;
  737.             } else {
  738.                 ctrlDescPtr->part = thePart;
  739.             }
  740.             ctrlDescPtr->ctlRank = ControlRank;
  741.             
  742.             /* Special case TScrollBar to have ctlDefID of 16 so VU views it as a standard scroll bar */
  743.             if (MA_MEMBER(theControl, TScrollBar))
  744.             {
  745.                 ctrlDescPtr->ctlDefID = 16;
  746.             }
  747.             else
  748.             {
  749.                 ctrlDescPtr->ctlDefID = ::GetControlVariant(ControlHdl);
  750.             }
  751.             
  752.             ctrlDescPtr->ctlData.popupMenuID = 0;
  753.             MABlockMove((**ControlHdl).contrlTitle, ctrlDescPtr->ctlTitle.text, VUPLstrlen((**ControlHdl).contrlTitle)+1);
  754.  
  755.             /* this ugly thing computes the length (bytes used) of ctrlDescPtr */
  756.             *outputSize = sizeof(MoleControlDescriptor) - (255 - VUPLstrlen((**ControlHdl).contrlTitle));
  757.             
  758.             return TRUE;
  759.         }
  760.     }
  761.     return FALSE;
  762. }
  763.  
  764.  
  765. void TVUAssist::ViewRectToWindowRect (Rect *aRect, TView *aView)
  766. {
  767.     VPoint tl(aRect->left, aRect->top);
  768.     aView->LocalToWindow(tl);
  769.  
  770.     VPoint br(aRect->right, aRect->bottom);
  771.     aView->LocalToWindow(br);
  772.  
  773.     ::SetRect(aRect, (short)tl.h, (short)tl.v, (short)br.h, (short)br.v);
  774. }
  775.  
  776. /* Fill in a mole dialog item descriptor record */
  777.  
  778. void TVUAssist::FillDlogItemDesc (MoleDItemInfoPtr dlogDescPtr, TWindow *window,
  779.                                          short windowRank, short itemRank, TView *item,
  780.                                          short *outputSize, TGridItem *gridItem)
  781. {
  782.     VRect         aVRect;
  783.     CRect         aCRect;
  784.     long         textLen;
  785.     Handle         textHdl;
  786.     ViewItems     itemKind;
  787.     GridCell     aCell;
  788.     CStr255        theText;
  789.     
  790.     itemKind = this->GetItemType (item, TRUE, TRUE);
  791.  
  792.     /* fill in box, itemType, item_enabled, has_text and text_name here */
  793.     switch (itemKind) {
  794.  
  795.     case VINotMember:
  796.         break;
  797.  
  798.     case VIButton:
  799.         dlogDescPtr->itemType = btnCtrlItem;
  800.         dlogDescPtr->item_enabled = ((TCtlMgrPtr)(item))->IsCMgrVisible() && item->IsActive();
  801.         dlogDescPtr->has_text = TRUE;
  802.         ((TCtlMgrPtr)(item))->GetText(theText);
  803.         MABlockMove((unsigned char*)theText, dlogDescPtr->itemData.text, theText.Length()+1);
  804.         break;
  805.  
  806.     case VIRadio:
  807.         ((TCtlMgrPtr)(item))->ControlArea (aVRect);
  808.         dlogDescPtr->itemType = radCtrlItem;
  809.         dlogDescPtr->item_enabled = ((TCtlMgrPtr)(item))->IsCMgrVisible() && item->IsActive();
  810.         dlogDescPtr->has_text = TRUE;
  811.         ((TCtlMgrPtr)(item))->GetText(theText);
  812.         MABlockMove((unsigned char*)theText, dlogDescPtr->itemData.text, theText.Length()+1);
  813.         break;
  814.  
  815.     case VICheckBox:
  816.         ((TCtlMgrPtr)(item))->ControlArea (aVRect);
  817.         dlogDescPtr->itemType = chkCtrlItem;
  818.         dlogDescPtr->item_enabled = ((TCtlMgrPtr)(item))->IsCMgrVisible() && item->IsActive();
  819.         dlogDescPtr->has_text = TRUE;
  820.         ((TCtlMgrPtr)(item))->GetText(theText);
  821.         MABlockMove((unsigned char*)theText, dlogDescPtr->itemData.text, theText.Length()+1);
  822.         break;
  823.  
  824.     case VIScrollBar:
  825.         ((TCtlMgrPtr)(item))->ControlArea (aVRect);
  826.         dlogDescPtr->itemType = resCtrlItem;
  827.         dlogDescPtr->item_enabled = ((TCtlMgrPtr)(item))->IsCMgrVisible() && item->IsActive();
  828.         dlogDescPtr->has_text = TRUE;
  829.         ((TCtlMgrPtr)(item))->GetText(theText);
  830.         MABlockMove((unsigned char*)theText, dlogDescPtr->itemData.text, theText.Length()+1);
  831.         break;
  832.  
  833.     case VIStatText:
  834.         aVRect = item->GetExtent();
  835.         dlogDescPtr->itemType = statText;
  836.         dlogDescPtr->item_enabled = FALSE;
  837.         dlogDescPtr->has_text = TRUE;
  838.         ((TStaticTextPtr)(item))->GetText(theText);
  839.         MABlockMove((unsigned char*)theText, dlogDescPtr->itemData.text, theText.Length()+1);
  840.         break;
  841.  
  842.     case VIEditText:
  843.         aVRect = item->GetExtent();
  844.         dlogDescPtr->itemType = editText;
  845.         dlogDescPtr->item_enabled = item->IsActive();
  846.         dlogDescPtr->has_text = TRUE;
  847.         ((TEditTextPtr)(item))->GetText(theText);
  848.         MABlockMove((unsigned char*)theText, dlogDescPtr->itemData.text, theText.Length()+1);
  849.         break;
  850.  
  851.     case VIIcon:
  852.         aVRect = item->GetExtent();
  853.         dlogDescPtr->itemType = iconItem;
  854.         dlogDescPtr->item_enabled = item->IsActive();
  855.         dlogDescPtr->has_text = FALSE;
  856.         dlogDescPtr->itemData.item_text_ptr = NULL;
  857.         break;
  858.  
  859.     case VIPopup:
  860.         aVRect = item->GetExtent();
  861.         dlogDescPtr->itemType = resCtrlItem;
  862.         dlogDescPtr->item_enabled = item->IsActive();
  863.         dlogDescPtr->has_text = FALSE;
  864.         dlogDescPtr->itemData.item_text_ptr = NULL;
  865.         break;
  866.  
  867.     case VIPicture:
  868.         aVRect = item->GetExtent();
  869.         dlogDescPtr->itemType = picItem;
  870.         dlogDescPtr->item_enabled = item->IsActive();
  871.         dlogDescPtr->has_text = FALSE;
  872.         dlogDescPtr->itemData.item_text_ptr = NULL;
  873.         break;
  874.  
  875.     case VITextEdit:
  876.         aVRect = item->GetExtent();
  877.         dlogDescPtr->itemType = editText;
  878.         dlogDescPtr->item_enabled = item->IsActive();
  879.         dlogDescPtr->has_text = TRUE;
  880.         textHdl = TTEViewPtr(item)->ExtractText();
  881.         textLen = ::GetHandleSize(textHdl);
  882.         if (textLen > 255)
  883.             textLen = 255;
  884.         MABlockMove(*textHdl, dlogDescPtr->itemData.text, textLen);
  885.         break;
  886.  
  887.     case VIGridItem:
  888.         gridItem->GetExtent(aVRect);
  889.         dlogDescPtr->itemType = CUSTOM_ITEM;
  890.         dlogDescPtr->item_enabled = gridItem->fGridView->IsActive();
  891.         if (MA_MEMBER(item, TTextGridView)) {
  892.             dlogDescPtr->has_text = TRUE;
  893.             aCell.v = (short)gridItem->fRow;
  894.             aCell.h = (short)gridItem->fColumn;
  895.             TTextGridViewPtr(gridItem->fGridView)->GetText(aCell, theText);
  896.             MABlockMove((unsigned char*)theText, dlogDescPtr->itemData.text, theText.Length()+1);
  897.         } 
  898.         else {
  899.             dlogDescPtr->has_text = FALSE;
  900.             dlogDescPtr->itemData.item_text_ptr = NULL;
  901.         }
  902.         break;
  903.     }
  904.  
  905.     VRectToRect(aVRect, aCRect);
  906.     ::SetRect(&dlogDescPtr->box, aCRect.left,aCRect.top,aCRect.right,aCRect.bottom);
  907.     this->ViewRectToWindowRect (&dlogDescPtr->box, item);
  908.  
  909.     /* fill in ctlRank, owner_rank, and item_num here */
  910.     dlogDescPtr->ctlRank = this->ItemToRank (window, item, FALSE);
  911.     dlogDescPtr->owner_rank = windowRank;
  912.     dlogDescPtr->item_num = itemRank;
  913.  
  914.     /* this ugly thing computes the length (bytes used) of MoleDItemInfo */
  915.     if (itemKind != VINotMember) 
  916.     {
  917.         *outputSize = sizeof(MoleDItemInfo) - (255 - dlogDescPtr->itemData.text[0]);
  918.     }
  919.  
  920.     if (gridItem) {
  921.         gridItem->Free();
  922.     }
  923. }
  924.  
  925.  
  926. /* ------------------------------------------------------------------------------------ */
  927. /* routines for searching through the view tree to find particular views */
  928.  
  929. /* Given the rank (z-order) of a window, return the window object.  Invisible
  930. windows are not considered to be in the window list, for ranking purposes. */
  931.  
  932. TWindow *TVUAssist::RankToWindow (short rank)
  933. {
  934.     short i = 1;
  935.     WindowRef window = ::FrontWindow();
  936.  
  937.     while (window) {
  938.         if (IsWindowVisible(window)) {
  939.             if (i == rank) {
  940.                 return gApplication->WMgrToWindow(window);
  941.             }
  942.             i = i+1;
  943.         }
  944.         window = GetNextWindow(window);
  945.     }
  946.  
  947.     return NULL;
  948. }
  949.  
  950.  
  951. /* Given a window ptr, return the window's rank (z-order) */
  952.  
  953. short TVUAssist::WindowToRank (WindowRef WindToFind)
  954. {
  955.     short i = 1;
  956.     WindowRef window = ::FrontWindow();
  957.  
  958.     while (window) {
  959.         if (IsWindowVisible(window)) {
  960.             if (WindToFind == window) {
  961.                 return i;
  962.             }
  963.             i = i+1;
  964.         }
  965.         window = GetNextWindow(window);
  966.     }
  967.  
  968.     return 0;
  969. }
  970.  
  971.  
  972. /* Convert a point in global coordinates to window coordinates. */
  973.  
  974. void TVUAssist::GlobalToWindow (TWindow *window, Point Pt, VPoint *VPt)
  975. {
  976.     VPt->h = 0;
  977.     VPt->v = 0;
  978.  
  979.     GrafPtr savePort;
  980.     ::GetPort(&savePort);
  981.     ::SetPort(window->GetGrafPort());
  982.     if (window->Focus())
  983.     {
  984.         CPoint targetPoint(Pt);
  985.         GlobalToLocal(&targetPoint);
  986.         *VPt = window->QDToViewPt(targetPoint);
  987.     }
  988.     ::SetPort(savePort);
  989. }
  990.  
  991.  
  992. /* Convert a point in window coordinates to a subview's coordinates. Return both a
  993. VPoint and a QDPoint. */
  994.  
  995. void TVUAssist::WindowToView (TView *view, VPoint *VPt, Point *Pt)
  996. {
  997.     Pt->h = 0;
  998.     Pt->v = 0;
  999.     view->WindowToLocal(*VPt);
  1000.     if (view->Focus()) {
  1001.         Pt = view->ViewToQDPt (*VPt);
  1002.     }
  1003. }
  1004.  
  1005.  
  1006. /* In the front (active) window, given the menu ID of a popup item, return the  
  1007. popup menu object and its rank. */
  1008.  
  1009. static TView *FoundView_MenuIDToPopup = NULL;
  1010. static short MenuID_MenuIDToPopup;
  1011.  
  1012. static Boolean TestSubID_MenuIDToPopup(TView *theSubView, TVUAssist *self)
  1013. {
  1014.     if (theSubView->IsShown()) {
  1015.         if (self->GetItemType(theSubView, FALSE, FALSE) == VIPopup) {
  1016.             if (TPopupPtr(theSubView)->fMenuID == MenuID_MenuIDToPopup) {
  1017.                 FoundView_MenuIDToPopup = theSubView;
  1018.             }
  1019.         }
  1020.         if (FoundView_MenuIDToPopup == NULL) {
  1021.             CSubViewIterator iter(theSubView);
  1022.             for (TView * aView = iter.FirstSubView(); iter.More(); aView = iter.NextSubView()) {
  1023.                 if (TestSubID_MenuIDToPopup(aView, self))
  1024.                     break;
  1025.             }
  1026.         }
  1027.     }
  1028.     return FoundView_MenuIDToPopup != NULL;
  1029. }
  1030.  
  1031. TPopup *TVUAssist::MenuIDToPopup (short menuID)
  1032. {
  1033.     FoundView_MenuIDToPopup = NULL;
  1034.     MenuID_MenuIDToPopup = menuID;
  1035.  
  1036.     TWindow *window = gApplication->GetActiveWindow(TRUE);
  1037.  
  1038.     if (window && window->IsShown()) {
  1039.         CSubViewIterator iter(window);
  1040.         for (TView * aView = iter.FirstSubView(); iter.More(); aView = iter.NextSubView()) {
  1041.             if (TestSubID_MenuIDToPopup(aView, this))
  1042.                 break;
  1043.         }
  1044.     }
  1045.     return TPopupPtr(FoundView_MenuIDToPopup);
  1046. }
  1047.  
  1048.  
  1049. /* Given a window object and a point in global coordinates,
  1050. find the control which is under that point. Only descendants of
  1051. TCtlMgr are considered.*/
  1052.  
  1053. static TView *FoundView_PointToControl;
  1054. static VPoint VPt_PointToControl;
  1055.  
  1056. static Boolean TestSubView_PointToControl(TView *theSubView, TVUAssist *self)
  1057. {
  1058.     VPoint testPoint;
  1059.     Point dummyPoint;
  1060.  
  1061.     if (theSubView->IsShown()) {
  1062.         if (MA_MEMBER(theSubView, TCtlMgr)) {
  1063.             testPoint = VPt_PointToControl;
  1064.             self->WindowToView (theSubView, &testPoint, &dummyPoint);
  1065.             if (theSubView->ContainsMouse(testPoint)) {
  1066.                 FoundView_PointToControl = theSubView;
  1067.             }
  1068.         }
  1069.         if (FoundView_PointToControl == NULL) {
  1070.             CSubViewIterator iter(theSubView);
  1071.             for (TView * aView = iter.FirstSubView(); iter.More(); aView = iter.NextSubView()) {
  1072.                 if (TestSubView_PointToControl(aView, self))
  1073.                     break;
  1074.             }
  1075.         }
  1076.     }
  1077.     return FoundView_PointToControl != NULL;
  1078. }
  1079.  
  1080.  
  1081. TCtlMgr *TVUAssist::PointToControl (TWindow *window, Point Pt, short *rank)
  1082. {
  1083.     FoundView_PointToControl = NULL;
  1084.     this->GlobalToWindow (window, Pt, &VPt_PointToControl);
  1085.  
  1086.     if (window->IsShown()) {
  1087.         CSubViewIterator iter(window);
  1088.         for (TView * aView = iter.FirstSubView(); iter.More(); aView = iter.NextSubView()) {
  1089.             if (TestSubView_PointToControl(aView, this))
  1090.                 break;
  1091.         }
  1092.     }
  1093.  
  1094.     *rank = this->ItemToRank (window, FoundView_PointToControl, FALSE);
  1095.     return TCtlMgrPtr(FoundView_PointToControl);
  1096. }
  1097.  
  1098. static short ItemCount_ViewCount = 0;
  1099.  
  1100. static void DoToSubView_ViewCount(TView *theSubView, TVUAssist *self, Boolean dlogViewItems)
  1101. {
  1102.     if (theSubView->IsShown()) {
  1103.  
  1104.         ViewItems ItemType = self->GetItemType (theSubView, dlogViewItems, dlogViewItems);
  1105.         if (ItemType != VINotMember) {
  1106.             if (ItemType == VIGridItem) {
  1107.                 ItemCount_ViewCount += self->CountGridItems (TGridViewPtr(theSubView));
  1108.             } else {
  1109.                 ItemCount_ViewCount++;
  1110.             }
  1111.         }
  1112.         if (MA_MEMBER(theSubView, TView)) {
  1113.             CSubViewIterator iter(theSubView);
  1114.             for (TView * aView = iter.FirstSubView(); iter.More(); aView = iter.NextSubView()) {
  1115.                 DoToSubView_ViewCount(aView, self, dlogViewItems);
  1116.             }
  1117.         }
  1118.     }
  1119. }
  1120.  
  1121.  
  1122. /* Walk the view hierarchy tree, counting the number of user interface items.
  1123. Only visible views and items are counted. */
  1124.  
  1125. short TVUAssist::ViewCount (TWindow *window, Boolean dlogViewItems)
  1126. {
  1127.     ItemCount_ViewCount = 0;
  1128.     
  1129.     if (window->IsShown()) {
  1130.         CSubViewIterator iter(window);
  1131.         for (TView * aView = iter.FirstSubView(); iter.More(); aView = iter.NextSubView()) {
  1132.             DoToSubView_ViewCount(aView, this, dlogViewItems);
  1133.         }
  1134.     }
  1135.     return ItemCount_ViewCount;
  1136. }
  1137.  
  1138.  
  1139. /* Given a control or dialog item (view), and the window its in (window), return its rank. */
  1140.  
  1141. static short ItemCount_ItemToRank;
  1142. static short Rank_ItemToRank;
  1143. static TView *View_ItemToRank;
  1144.  
  1145. static Boolean TestSubView_ItemToRank(TView *theSubView, TVUAssist *self, Boolean dlogViewItems)
  1146. {
  1147.     if (theSubView->IsShown()) {
  1148.  
  1149.         ViewItems ItemType = self->GetItemType (theSubView, dlogViewItems, dlogViewItems);
  1150.         if (ItemType != VINotMember) {
  1151.             if (ItemType == VIGridItem) {
  1152.                 if (MA_MEMBER(View_ItemToRank, TGridItem) && (theSubView == TGridItemPtr(View_ItemToRank)->fGridView)) {
  1153.                     Rank_ItemToRank = ItemCount_ItemToRank + (short)(TGridItemPtr(View_ItemToRank)->fRank);
  1154.                 } else {
  1155.                     ItemCount_ItemToRank += self->CountGridItems (TGridViewPtr(theSubView));
  1156.                 }
  1157.             } else {
  1158.                 ItemCount_ItemToRank++;
  1159.                 if (theSubView == View_ItemToRank) {
  1160.                     Rank_ItemToRank = ItemCount_ItemToRank;
  1161.                 }
  1162.             }
  1163.         }
  1164.         if (Rank_ItemToRank == 0) {
  1165.             CSubViewIterator iter(theSubView);
  1166.             for (TView * aView = iter.FirstSubView(); iter.More(); aView = iter.NextSubView()) {
  1167.                 if (TestSubView_ItemToRank(aView, self, dlogViewItems))
  1168.                     break;
  1169.             }
  1170.         }
  1171.     }
  1172.     return Rank_ItemToRank != 0;
  1173. }
  1174.  
  1175.  
  1176. short TVUAssist::ItemToRank (TWindow *window, TView *view, Boolean dlogViewItems)
  1177. {
  1178.     Rank_ItemToRank = 0;
  1179.     ItemCount_ItemToRank = 0;
  1180.     View_ItemToRank = view;
  1181.  
  1182.     if (window->IsShown()) {
  1183.         CSubViewIterator iter(window);
  1184.         for (TView * aView = iter.FirstSubView(); iter.More(); aView = iter.NextSubView()) {
  1185.             if (TestSubView_ItemToRank(aView, this, dlogViewItems))
  1186.                 break;
  1187.         }
  1188.     }
  1189.     return Rank_ItemToRank;
  1190. }
  1191.  
  1192.  
  1193. static TView *FoundView_RankToItem;
  1194. static short ItemCount_RankToItem;
  1195. static short Rank_RankToItem;
  1196. static Boolean DlogViewItems_RankToItem;
  1197.  
  1198. /* Given a window object and the rank (z-order) of an item, return the item object. If
  1199. the item is a cell of a TGridView object, return that object in gridItem.*/
  1200.  
  1201. static Boolean TestSubView_RankToItem(TView *theSubView, TVUAssist *self, TGridItem*& gridItem)
  1202. {
  1203.     if (theSubView->IsShown()) {
  1204.  
  1205.         ViewItems ItemType = self->GetItemType (theSubView, DlogViewItems_RankToItem, DlogViewItems_RankToItem);
  1206.         if (ItemType != VINotMember) {
  1207.             if (ItemType == VIGridItem) {
  1208.                 short GridCount = self->CountGridItems (TGridViewPtr(theSubView));
  1209.                 if ((Rank_RankToItem > ItemCount_RankToItem) && (Rank_RankToItem <= ItemCount_RankToItem + GridCount)) {
  1210.                     gridItem = new TGridItem;
  1211.                     gridItem->IGridItem(TGridViewPtr(theSubView), Rank_RankToItem - ItemCount_RankToItem);
  1212.                     FoundView_RankToItem = theSubView;
  1213.                 }
  1214.                 ItemCount_RankToItem += GridCount;
  1215.             } else {
  1216.                 ItemCount_RankToItem++;
  1217.                 if (ItemCount_RankToItem == Rank_RankToItem) {
  1218.                     FoundView_RankToItem = theSubView;
  1219.                 }
  1220.             }
  1221.         }
  1222.         if (FoundView_RankToItem == NULL) {
  1223.             CSubViewIterator iter(theSubView);
  1224.             for (TView * aView = iter.FirstSubView(); iter.More(); aView = iter.NextSubView()) {
  1225.                 if (TestSubView_RankToItem(aView, self, gridItem))
  1226.                     break;
  1227.             }
  1228.         }
  1229.     }
  1230.     return FoundView_RankToItem != NULL;
  1231. }
  1232.  
  1233.  
  1234. TView *TVUAssist::RankToItem (TWindow *window, short rank, Boolean dlogViewItems, TGridItem*& gridItem)
  1235. {
  1236.     FoundView_RankToItem = NULL;
  1237.     ItemCount_RankToItem = 0;
  1238.     Rank_RankToItem = rank;
  1239.     DlogViewItems_RankToItem = dlogViewItems;
  1240.  
  1241.     if (window->IsShown()) {
  1242.         CSubViewIterator iter(window);
  1243.         for (TView * aView = iter.FirstSubView(); iter.More(); aView = iter.NextSubView()) {
  1244.             if (TestSubView_RankToItem(aView, this, gridItem))
  1245.                 break;
  1246.         }
  1247.     }
  1248.     return FoundView_RankToItem;
  1249. }
  1250.  
  1251.  
  1252. /* Report the number of items in a TGridView.  This is here so it can
  1253. be easily overridden if you only want rows or columns to show up as
  1254. seperate user interface items, instead of each cell. */
  1255.  
  1256. short TVUAssist::CountGridItems (TGridView *theGridView)
  1257. {
  1258.     return theGridView->fNumOfRows * theGridView->fNumOfCols;
  1259. }
  1260.  
  1261.  
  1262. /* Given a view item and the control/dialog item flag, decide if this
  1263. view object is a control if the flag=ControlsOnly, or if its a dialog
  1264. item if the flag=DialogItems, or if its neither.  Of course, MacApp 
  1265. doesn't have a concept of dialog items, so we improvise.  Here are the criteria.
  1266. Any descendent of TCtlMgr is a control.  Descendants of TPopup are also classified
  1267. as contols because V.U. can normally only deal with popups which utilize the popup
  1268. CDEF.  So V.U. expects popups to be controls.
  1269. Descendents of TTEView and some descendants of TControl (specifically TEditText, 
  1270. TStaticText, TIcon, TPicture, and TGridView) are considered to be DialogItems for V.U.'s sake.  
  1271. gridViewItems are considered along with other dlogViewItems only if gridViewItems parameter 
  1272. is true.*/
  1273.  
  1274. ViewItems TVUAssist::GetItemType (TView *item, Boolean dlogViewItems, Boolean gridViewItems)
  1275. {
  1276.     if (MA_MEMBER(item, TPopup)) return VIPopup;
  1277.     if (MA_MEMBER(item, TRadio)) return VIRadio;
  1278.     if (MA_MEMBER(item, TCheckBox)) return VICheckBox;
  1279.     if (MA_MEMBER(item, TScrollBar)) return VIScrollBar;
  1280.     if (MA_MEMBER(item, TButton)) return VIButton;
  1281.  
  1282.     if (dlogViewItems) {
  1283.         if (MA_MEMBER(item, TEditText)) return VIEditText;
  1284.         if (MA_MEMBER(item, TStaticText)) return VIStatText;
  1285.         if (MA_MEMBER(item, TIcon)) return VIIcon;
  1286.         if (MA_MEMBER(item, TPicture)) return VIPicture;
  1287.         if (MA_MEMBER(item, TTEView) && ! MA_MEMBER(item, TDialogTEView))
  1288.             return VITextEdit;
  1289.         if (fGridItemSupport && gridViewItems) {
  1290.             if (MA_MEMBER(item, TGridView))
  1291.                 return VIGridItem;
  1292.         }
  1293.     }
  1294.  
  1295.     return VINotMember;
  1296. }
  1297.  
  1298.  
  1299. /*========================================== TGridItem ================================*/
  1300.  
  1301. #undef Inherited
  1302. #define Inherited TObject
  1303.  
  1304. #pragma segment AInit
  1305. MA_DEFINE_CLASS_M1(TGridItem, Inherited);
  1306.  
  1307. //----------------------------------------------------------------------------------------
  1308. // TGridItem destructor
  1309. //----------------------------------------------------------------------------------------
  1310. #pragma segment MADestructorRes
  1311.  
  1312. TGridItem::~TGridItem()
  1313. {
  1314. }
  1315.     
  1316. #pragma segment AVUAssist2
  1317.  
  1318. /* Instantiate a TGridItem object, and fill in its fields..  This is here 
  1319. so it can be overridden if you only want rows or columns to show 
  1320. up as seperate user interface items, instead of each individual cells. */
  1321.  
  1322. void TGridItem::IGridItem (TGridView *theGridView, short rank)
  1323. {
  1324.     this->IObject();
  1325.     this->fGridView = theGridView;
  1326.     this->fRank = rank;
  1327.     this->fRow = (rank - 1) / theGridView->fNumOfCols +1;
  1328.     this->fColumn = (rank - 1) % theGridView->fNumOfCols +1;
  1329. }
  1330.  
  1331. /* Provide the bounding rect of a griditem */
  1332.  
  1333. void TGridItem::GetExtent (VRect& itsExtent)
  1334. {
  1335.     GridCell aCell((short)fColumn, (short)fRow);
  1336.     fGridView->CellToVRect (aCell, itsExtent);
  1337. }
  1338.  
  1339.  
  1340. /* call the LocalToWindow method of the GridView associated with the griditem */
  1341.  
  1342. void TGridItem::LocalToWindow(VPoint *thePoint)
  1343. {
  1344.     fGridView->LocalToWindow(*thePoint);
  1345. }
  1346.  
  1347. #endif // of #if qNeedsVU
  1348.  
  1349. //----------------------------------------------------------------------------------------
  1350. // End of UVUAssist.cp
  1351.  
  1352. #pragma segment Inline
  1353.